package edu.isistan.parser;

import java.util.Hashtable;
import java.util.Vector;

import edu.isistan.metamodel.DataType;


/**
 * Compares two datatypes 
 */
public class TypeComparator {
	private Hashtable<String, Integer> integerGroup = new Hashtable<String, Integer>();
	private Hashtable<String, Integer> decimalNumberGroup = new Hashtable<String, Integer>();
	private Hashtable<String, Integer> stringGroup = new Hashtable<String, Integer>();
	private Hashtable<String, Integer> booleanGroup = new Hashtable<String, Integer>();
	private Vector<String> wrappers = new Vector<String>();
	private static TypeComparator instance = null;
	
	protected TypeComparator() {
		integerGroup.put("Object",-1);
		integerGroup.put("java.lang.Object",-1);
		integerGroup.put("byte",0);
		integerGroup.put("java.lang.Byte",0);
		integerGroup.put("short",1);
		integerGroup.put("java.lang.Short",1);
		integerGroup.put("int",2);
		integerGroup.put("java.lang.Integer",2);		
		integerGroup.put("long",3);
		integerGroup.put("java.lang.Long",3);
		
		decimalNumberGroup.put("Object",-1);
		decimalNumberGroup.put("java.lang.Object",-1);
		decimalNumberGroup.put("float",0);
		decimalNumberGroup.put("java.lang.Float",0);
		decimalNumberGroup.put("double",1);
		decimalNumberGroup.put("java.lang.Double",1);
		decimalNumberGroup.put("java.math.BigDecimal",1);
		
		stringGroup.put("Object",-1);
		stringGroup.put("java.lang.Object",-1);
		stringGroup.put("char",0);
		stringGroup.put("String",1);stringGroup.put("string",1);
		stringGroup.put("java.lang.String",1);
		
		booleanGroup.put("Object",-1);
		booleanGroup.put("java.lang.Object",-1);
		booleanGroup.put("boolean",0);
		booleanGroup.put("java.lang.Boolean",0);
		wrappers.add("java.lang.Byte");
		wrappers.add("java.lang.Short");
		wrappers.add("java.lang.Integer");
		wrappers.add("java.lang.Long");
		wrappers.add("java.lang.Integer");
		wrappers.add("java.lang.Float");
		wrappers.add("java.lang.Double");
		//wrappers.add("java.lang.Character");
		wrappers.add("java.lang.Boolean");		
	}
	
	public static TypeComparator getInstance(){
		if(instance == null)
			instance = new TypeComparator();
		return instance;
	}
	
	public boolean equals(DataType t1, DataType t2){
		return t1.getType().equals(t2.getType());
	}
		
	public boolean compatible(DataType t1, DataType t2){
		if(sameGroup(t1,t2))
			return true;
		else
			return false;
	}
	
	public boolean lost(DataType t1, DataType t2){
		if(integerGroup.containsKey(t1.getType()) && integerGroup.containsKey(t2.getType())){
			if(integerGroup.get(t1.getType()) > integerGroup.get(t2.getType()))
				return true;
			else return false;
		}
		if(decimalNumberGroup.containsKey(t1.getType()) && decimalNumberGroup.containsKey(t2.getType())){
			if(decimalNumberGroup.get(t1.getType()) > decimalNumberGroup.get(t2.getType()))
				return true;
			else return false;
		}
		if(stringGroup.containsKey(t1.getType()) && stringGroup.containsKey(t2.getType())){
			if(stringGroup.get(t1.getType()) > stringGroup.get(t2.getType()))
				return true;
			else return false;
		}
		return false;
	}

	private boolean sameGroup(DataType t1, DataType t2) {
		if(integerGroup.containsKey(t1.getType()) && integerGroup.containsKey(t2.getType()))
			return true;
		if(decimalNumberGroup.containsKey(t1.getType()) && decimalNumberGroup.containsKey(t2.getType()))
			return true;
		if(stringGroup.containsKey(t1.getType()) && stringGroup.containsKey(t2.getType()))
			return true;
		if(booleanGroup.containsKey(t1.getType()) && booleanGroup.containsKey(t2.getType()))
			return true;
		return false;
	}	
	
//	public double checkCardinalities(DataType t1, DataType t2){
//		if(t1.getCardinality() != t2.getCardinality()){
//			return CARDINALITY_MISMATCH_PENALTY;
//		}
//		return 0.0;
//	}
//	
//	public double checkParameterSizes(int size1, int size2){
//		if(size1 < size2)
//			return (size2 - size1) * Tunning.PARAMETER_PARAMETERS_1_SIZE_NON_MATCHED;
//		else if (size1 > size2)
//			return (size1 - size2) * Tunning.PARAMETER_PARAMETERS_2_SIZE_NON_MATCHED;
//		return 0.0;
//	}
	
	public boolean isWrapper(String typeToCompare){
		for(String type : wrappers)
			if(typeToCompare.startsWith(type))
				return true;
		return false;
	}	
}
